
#include "stm32f2xx.h"
#include <time.h>
#include "stm32_util.h"


/*
*	Jan - 1, Feb - 2, Mar - 3, Apr -  4, May -  5, Jun -  6
*	Jul - 7, Aug - 8, Sep - 9, Oct - 10, Nov - 11, Dec - 12
* __DATE__ : Apr  6 2012
* __TIME__ : 17:21:13
*/
#define	DIGIT(s, no)	((s)[no] - '0')
const int _year_ = (1000*DIGIT(__DATE__, 7) + 100*DIGIT(__DATE__, 8) + 10*DIGIT(__DATE__, 9) + DIGIT(__DATE__, 10));
const int _month_ = (__DATE__[2] == 'b' ? 2 : (__DATE__[2] == 'y' ? 5 : (__DATE__[2] == 'l' ? 7 : (__DATE__[2] == 'g' ? 8 :
	(__DATE__[2] == 'p' ? 9 : (__DATE__[2] == 't' ? 10 : (__DATE__[2] == 'v' ? 11 : (__DATE__[2] == 'c' ? 12 :
	(__DATE__[2] == 'n' ? (__DATE__[1] == 'a' ? 1 : 6) : (__DATE__[1] == 'a' ? 3 : 4))))))))));
const int _day_ = ( 10 * (__DATE__[4] == ' ' ? 0 : DIGIT(__DATE__, 4)) + DIGIT(__DATE__, 5));
const int _hour_ = (10 * DIGIT(__TIME__, 0) + DIGIT(__TIME__, 1));
const int _minute_ = (10 * DIGIT(__TIME__, 3) + DIGIT(__TIME__, 4));
const int _second_ = (10 * DIGIT(__TIME__, 6) + DIGIT(__TIME__, 7));
time_t Util_GetBuildTime(void)
{
	struct tm sTM;

	sTM.tm_sec  = _second_;			// Seconds after minute (0 ~ 59) 
	sTM.tm_min  = _minute_;			// Minutes after hour (0 ~ 59) 
	sTM.tm_hour = _hour_;			// Hours since midnight (0 ~ 23)
	sTM.tm_mday = _day_;			// Day of month (1 ~ 31) 
	sTM.tm_mon  = _month_ - 1;		// Month (0 ~ 11; January = 0) 
	sTM.tm_year = _year_ - 1900;	// Year (current year minus 1900)

	return mktime(&sTM);
}

void Util_GpioInit(GPIO_INIT *gis, uc32 count)
{
	u32 i;

	for (i=0; i<count; i++)
	{
		RCC_AHB1PeriphClockCmd(gis[i].AHB1Clk, ENABLE);
		GPIO_Init(gis[i].Port, &gis[i].Gpio);
		if (GPIO_Mode_AF == gis[i].Gpio.GPIO_Mode)
		{
			switch (gis[i].AFType)
			{
			case eAFCLK_AHB1:
				RCC_AHB1PeriphClockCmd(gis[i].AFClk, ENABLE);
				break;
			case eAFCLK_AHB2:
				RCC_AHB2PeriphClockCmd(gis[i].AFClk, ENABLE);
				break;
			case eAFCLK_APB1:
				RCC_APB1PeriphClockCmd(gis[i].AFClk, ENABLE);
				break;
			case eAFCLK_APB2:
				RCC_APB2PeriphClockCmd(gis[i].AFClk, ENABLE);
				break;
			default:
				continue;
			}
			GPIO_PinAFConfig(gis[i].Port, gis[i].AFPinSrc, gis[i].AF);
		}
	}
}

void Util_ExtiInit(EXTI_INIT *eis, uc32 count)
{
	u32 i;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	for (i=0; i<count; i++)
	{
		SYSCFG_EXTILineConfig(eis[i].PortSrc, eis[i].PinSrc);
		EXTI_Init((EXTI_InitTypeDef *)&eis[i].Exti);
		//EXTI_GenerateSWInterrupt(eis[i].Exti.EXTI_Line);
		NVIC_Init((NVIC_InitTypeDef *)&eis[i].Nvic);
	}
}

void Util_UartInit(UART_INIT *uis, uc32 count)
{
	u32 i;

	for (i=0; i<count; i++)
	{
		USART_DeInit(uis[i].Port);

		if (3750000 == uis[i].Uart.USART_BaudRate)
			USART_OverSampling8Cmd(uis[i].Port, ENABLE);

		USART_Init(uis[i].Port, &uis[i].Uart);
		USART_Cmd(uis[i].Port, ENABLE);
		NVIC_Init((NVIC_InitTypeDef *)&uis[i].Nvic);
		USART_ITConfig(uis[i].Port, USART_IT_RXNE, ENABLE);
	}
}

u32 Util_IsResetWWDG(void)
{
	if (RESET != RCC_GetFlagStatus(RCC_FLAG_WWDGRST))
	{
		/* Clear reset flags */
	    RCC_ClearFlag();

		return 1;
	}

	return 0;
}
void Util_ResetWWDG(void)
{
	/* Enable WWDG clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);

	/* WWDG clock counter = (PCLK1 (30MHz)/4096)/8 = 915 Hz (~1092 us)  */
	WWDG_SetPrescaler(WWDG_Prescaler_8);

	/* Set Window value to 80; WWDG counter should be refreshed only when the counter
	is below 80 (and greater than 64) otherwise a reset will be generated */
	WWDG_SetWindowValue(80);

	/* Enable WWDG and set counter value to 127, WWDG timeout = ~1092 us * 64 = 69.9 ms 
	In this case the refresh window is: ~1092 * (127-80) = 51.3 ms < refresh window < ~1092 * 64 = 69.9ms */
	WWDG_Enable(127);

	while (1);
}

u8 Util_BoardAddr(void)
{
#if		defined(BSP_DEVICE_CAMERA)
#define gpio_MS_CLK		RCC_AHB1Periph_GPIOA
#define gpio_MS_PORT	GPIOA
#define gpio_MS_PIN		GPIO_Pin_5
#define gpio_RL_CLK		RCC_AHB1Periph_GPIOA
#define gpio_RL_PORT	GPIOA
#define gpio_RL_PIN		GPIO_Pin_6

	GPIO_INIT gis[] =
	{
		{gpio_MS_CLK, {gpio_MS_PIN, GPIO_Mode_IN, GPIO_Speed_2MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_MS_PORT,},
		{gpio_RL_CLK, {gpio_RL_PIN, GPIO_Mode_IN, GPIO_Speed_2MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_RL_PORT,},
	};
	Util_GpioInit(gis, _countof(gis));

#if	1
	u8 right1_left0 = (gpio_RL_PORT->IDR & gpio_RL_PIN) ? 0x10 : 0;
	return right1_left0 ? 2 : 1/*DEV_CAMERA2 : DEV_CAMERA1*/;
#else
	u8 main1_sub0 = (gpio_MS_PORT->IDR & gpio_MS_PIN) ? 0x01 : 0;
	u8 right1_left0 = (gpio_RL_PORT->IDR & gpio_RL_PIN) ? 0x10 : 0;
	if (main1_sub0) {
		return right1_left0 ? 2 : 1/*DEV_CAMERA2 : DEV_CAMERA1*/;
	} else {
		return right1_left0 ? 4 : 3/*DEV_CAMERA4 : DEV_CAMERA3*/;
	}
#endif
#else
	return 0;/*DEV_TOUCH*/;
#endif
}

#define	_DEBUG	1
#if	_DEBUG
#include <stdio.h>	// printf()
#define	_dbg(x...)	printf(x);
#else
#define	_dbg(x...)
#endif
#include "app_flash_if.h"
u8 Util_FirmwareUpdate(uc32 uAddr, uc16 uTotalSize)
{
	u32 uFlashDst, uFlashDstEnd, uFlashSrc;

	if (0x8000000 == uAddr)
	{
		uFlashDst = APP_START_ADDRESS;
		uFlashDstEnd = APP_END_ADDRESS;
		uFlashSrc = SAVE_APP_START_ADDRESS;
	}
	else if (0x8010000 == uAddr)
	{
		uFlashDst = IAP_START_ADDRESS;
		uFlashDstEnd = IAP_END_ADDRESS;
		uFlashSrc = SAVE_IAP_START_ADDRESS;
	}
	else
	{
		_dbg("ERROR : Address(0x%X)\r\n", uAddr);
		return 1;
	}

	_dbg("+++ Util_FirmwareUpdate\r\n");
	if (uTotalSize)
	{
		FLASH_If_Erase(uFlashDst, uFlashDstEnd);
		_dbg(" FLASH_If_Erase(%d, %d)\r\n", uFlashDst, uFlashDstEnd);
	}
	for (u32 i=0; i<(uTotalSize/4); i++)
	{
		u32 uValue = *(__IO u32*)uFlashSrc;

		if (FLASH_COMPLETE != FLASH_ProgramWord(uFlashDst, uValue))
		{
			_dbg("ERROR : FLASH_ProgramWord(0x%X, 0x%X)\r\n", uFlashDst, uValue);
			return 2;
		}
		if (uValue != *(__IO u32*)uFlashDst)
		{
			_dbg("ERROR : 0x%X != 0x%X\r\n", uValue, *(__IO u32*)uFlashDst);
			return 3;
		}

		if (0 == (uFlashDst%60))	// 60 Bytes
		{
			_dbg(".");
		}
		uFlashDst += 4;
		uFlashSrc += 4;
	}
	_dbg("\r\n--- Util_FirmwareUpdate\r\n");

	return 0;
}

void Util_uDelay(uc32 usec)
{
	uint32_t count = 0;
	const uint32_t utime = (120 * usec / 7);
	do {
		if (++count > utime) {
			return;
		}
	} while (1);
}
void Util_mDelay(uc32 msec)
{
	Util_uDelay(msec * 1000);
}

